/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use crate::common::constants::*;
use crate::common::types::*;
use crate::{log_e, singleton_registry, Box, Vec};
#[cfg(any(test, feature = "test-utils"))]
use mockall::automock;

#[derive(Debug, Clone)]
pub struct Credential {
    pub user_id: i32,
    pub credential_id: CredentialId,
    pub template_id: TemplateId,
    pub auth_type: AuthType,
    pub executor_sensor_hint: u32,
    pub executor_matcher: u32,
    pub capability_level: AuthCapabilityLevel,
    pub credential_type: CredentialType,
    pub enrolled_sys_time: u64,
    pub abandon_sys_time: u64,
    pub abandon_flag: bool,
    pub storage_type: CredStorageType,
}

impl Credential {
    pub fn user_id(&self) -> i32 {
        self.user_id
    }

    pub fn credential_id(&self) -> CredentialId {
        self.credential_id
    }

    pub fn template_id(&self) -> TemplateId {
        self.template_id
    }

    pub fn auth_type(&self) -> AuthType {
        self.auth_type
    }

    pub fn executor_sensor_hint(&self) -> u32 {
        self.executor_sensor_hint
    }

    pub fn executor_matcher(&self) -> u32 {
        self.executor_matcher
    }

    pub fn capability_level(&self) -> AuthCapabilityLevel {
        self.capability_level
    }

    pub fn credential_type(&self) -> CredentialType {
        self.credential_type
    }

    pub fn enrolled_sys_time(&self) -> u64 {
        self.enrolled_sys_time
    }

    pub fn abandon_sys_time(&self) -> u64 {
        self.abandon_sys_time
    }

    pub fn abandon_flag(&self) -> bool {
        self.abandon_flag
    }

    pub fn storage_type(&self) -> CredStorageType {
        self.storage_type
    }
}

#[derive(Debug, Clone)]
pub struct Enrolled {
    pub user_id: i32,
    pub enrolled_id: u64,
    pub auth_type: AuthType,
}

impl Enrolled {
    pub fn user_id(&self) -> i32 {
        self.user_id
    }

    pub fn enrolled_id(&self) -> u64 {
        self.enrolled_id
    }

    pub fn auth_type(&self) -> AuthType {
        self.auth_type
    }
}

#[derive(Debug, Clone)]
pub struct User {
    pub user_id: i32,
    pub sec_uid: u64,
    pub user_type: UserType,
    pub user_state: UserState,
}

impl User {
    pub fn user_id(&self) -> i32 {
        self.user_id
    }

    pub fn sec_uid(&self) -> u64 {
        self.sec_uid
    }

    pub fn user_type(&self) -> UserType {
        self.user_type
    }

    pub fn user_state(&self) -> UserState {
        self.user_state
    }
}

pub type CredentialFilter = Box<dyn Fn(&Credential) -> bool>;
pub type EnrolledIdFilter = Box<dyn Fn(&Enrolled) -> bool>;

#[cfg_attr(any(test, feature = "test-utils"), automock)]
pub trait UserDbManager {
    fn add_user(&mut self, user_id: i32, user_type: UserType) -> Result<(), ErrorCode>;
    fn get_user(&self, user_id: i32) -> Result<User, ErrorCode>;
    fn remove_user(&mut self, user_id: i32) -> Result<(), ErrorCode>;

    fn add_credential(&mut self, user_id: i32, credential_info: &Credential) -> Result<(), ErrorCode>;
    fn get_credential(&self, filter: CredentialFilter) -> Result<Credential, ErrorCode>;
    fn get_credential_list(&self, filter: CredentialFilter) -> Result<Vec<Credential>, ErrorCode>;
    fn remove_credential(&mut self, credential_id: CredentialId) -> Result<(), ErrorCode>;
    fn remove_pin_credential(&mut self, user_id: i32) -> Result<(), ErrorCode>;

    fn add_enrolled_id(&mut self, user_id: i32, enrolled_info: &Enrolled) -> Result<(), ErrorCode>;
    fn remove_enrolled_id(&mut self, user_id: i32, auth_type: AuthType) -> Result<(), ErrorCode>;
    fn get_enrolled_id(&self, user_id: i32, auth_type: AuthType) -> Result<u64, ErrorCode>;
    fn get_enrolled_id_list(&self, filter: EnrolledIdFilter) -> Result<Vec<Enrolled>, ErrorCode>;
    fn get_enrolled_list(&self, user_id: i32) -> Result<Vec<Enrolled>, ErrorCode>;

    fn generate_unique_sec_uid(&self) -> Result<u64, ErrorCode>;
    fn generate_unique_credential_id(&self) -> Result<u64, ErrorCode>;
    fn generate_unique_enrolled_id(&self) -> Result<u64, ErrorCode>;

    fn read_db(&mut self) -> Result<(), ErrorCode>;
    fn write_db(&mut self) -> Result<(), ErrorCode>;
    fn reload_db(&mut self) -> Result<(), ErrorCode>;

    fn check_user_type_valid(&self, _user_type: UserType) -> Result<bool, ErrorCode>;
    fn check_user_valid(&self, _user_id: i32) -> Result<bool, ErrorCode>;
    fn check_credential_valid(&self, _credential_id: CredentialId) -> Result<bool, ErrorCode>;
    fn check_enrolled_valid(&self, _user_id: i32, _auth_type: AuthType) -> Result<bool, ErrorCode>;

    fn get_all_user_id(&self) -> Result<Vec<i32>, ErrorCode>;
    fn get_all_credential_id(&self) -> Result<Vec<CredentialId>, ErrorCode>;
    fn get_all_enrolled_id(&self) -> Result<Vec<u64>, ErrorCode>;

    fn get_user_type(&self, _user_id: i32) -> Result<UserType, ErrorCode>;
    fn get_sec_uid(&self, _user_id: i32) -> Result<u64, ErrorCode>;
    fn get_pin_sub_type(&self, _user_id: i32) -> Result<i64, ErrorCode>;
    fn get_credential_valid_peroid(&self, _credential_id: CredentialId) -> Result<i64, ErrorCode>;
    fn get_enrolled_sys_time(&self, user_id: i32) -> Result<i64, ErrorCode>;
    fn get_user_id_by_template_id(&self, tempalte_id: TemplateId) -> Result<i32, ErrorCode>;
    fn get_credential_id_by_template_id(&self, tempalte_id: TemplateId) -> Result<CredentialId, ErrorCode>;

    fn get_pin_credential(&self, _user_id: i32) -> Result<Credential, ErrorCode>;
    fn get_abandon_pin_credential(&self, _user_id: i32) -> Result<Credential, ErrorCode>;

    fn check_specification(
        &self, _user_id: i32, _auth_type: AuthType, _schedule_type: ScheduleType) -> Result<(), ErrorCode>;
}

struct DummyUserDbManager;

impl UserDbManager for DummyUserDbManager {
    fn add_user(&mut self, _user_id: i32, _user_type: UserType) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_user(&self, _user_id: i32) -> Result<User, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn remove_user(&mut self, _user_id: i32) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn add_credential(&mut self, _user_id: i32, _credential_info: &Credential) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_credential(&self, _filter: CredentialFilter) -> Result<Credential, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_credential_list(
        &self,
        _filter: CredentialFilter,
    ) -> Result<Vec<Credential>, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn remove_credential(&mut self, _credential_id: CredentialId) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn remove_pin_credential(&mut self, _user_id: i32) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn add_enrolled_id(&mut self, _user_id: i32, _enrolled_info: &Enrolled) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn remove_enrolled_id(&mut self, _user_id: i32, _auth_type: AuthType) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_enrolled_id(&self, _user_id: i32, _auth_type: AuthType) -> Result<u64, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_enrolled_id_list(&self, _filter: EnrolledIdFilter) -> Result<Vec<Enrolled>, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_enrolled_list(&self, _user_id: i32) -> Result<Vec<Enrolled>, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn generate_unique_sec_uid(&self) -> Result<u64, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn generate_unique_credential_id(&self) -> Result<u64, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn generate_unique_enrolled_id(&self) -> Result<u64, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn read_db(&mut self) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn write_db(&mut self) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn reload_db(&mut self) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn check_user_type_valid(&self, _user_type: UserType) -> Result<bool, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn check_user_valid(&self, _user_id: i32) -> Result<bool, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn check_credential_valid(&self, _credential_id: CredentialId) -> Result<bool, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn check_enrolled_valid(&self, _user_id: i32, _auth_type: AuthType) -> Result<bool, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_all_user_id(&self) -> Result<Vec<i32>, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_all_credential_id(&self) -> Result<Vec<CredentialId>, ErrorCode>
    {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_all_enrolled_id(&self) -> Result<Vec<u64>, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_user_type(&self, _user_id: i32) -> Result<UserType, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_sec_uid(&self, _user_id: i32) -> Result<u64, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_pin_sub_type(&self, _user_id: i32) -> Result<i64, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_credential_valid_peroid(&self, _credential_id: CredentialId) -> Result<i64, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_enrolled_sys_time(&self, _user_id: i32) -> Result<i64, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_user_id_by_template_id(&self, _tempalte_id: TemplateId) -> Result<i32, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_credential_id_by_template_id(&self, _tempalte_id: TemplateId) -> Result<CredentialId, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_pin_credential(&self, _user_id: i32) -> Result<Credential, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn get_abandon_pin_credential(&self, _user_id: i32) -> Result<Credential, ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }

    fn check_specification(
        &self,
        _user_id: i32,
        _auth_type: AuthType,
        _schedule_type: ScheduleType
    ) -> Result<(), ErrorCode> {
        log_e!("not implemented");
        Err(ErrorCode::GeneralError)
    }
}

singleton_registry!(UserDbManagerRegistry, UserDbManager, DummyUserDbManager);
